package com.ruoyi.dm.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.CollectFileTypeConstants;
import com.ruoyi.common.core.domain.vo.CommonVO;
import com.ruoyi.common.enums.CollectFileStatusEnum;
import com.ruoyi.common.exception.DataRepeatException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.biz.BizModule;
import com.ruoyi.common.utils.biz.PathUtil;
import com.ruoyi.dm.component.AnalysisStrategyManager;
import com.ruoyi.dm.component.DataStrategyManager;
import com.ruoyi.dm.domain.CollectEstimateVO;
import com.ruoyi.dm.domain.CollectQueryParam;
import com.ruoyi.dm.domain.SpaceTrackDataCollectVO;
import com.ruoyi.dm.domain.po.SpaceTargetMeasurePO;
import com.ruoyi.dm.domain.po.SpaceTrackCollectRecordPO;
import com.ruoyi.dm.mapper.SpaceTrackCollectRecordMapper;
import com.ruoyi.dm.service.ISpaceTargetMeasureService;
import com.ruoyi.dm.service.ISpaceTrackCollectRecordService;
import com.ruoyi.utils.TranferUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SpaceTrackCollectRecordServiceImpl extends ServiceImpl<SpaceTrackCollectRecordMapper, SpaceTrackCollectRecordPO> implements ISpaceTrackCollectRecordService {
    @Autowired
    private ISpaceTrackCollectRecordService recordService;

    @Autowired
    private DataStrategyManager dataStrategyManager;

    @Autowired
    private AnalysisStrategyManager analysisStrategyManager;

    @Autowired
    private ISpaceTargetMeasureService measureService;

    @Override
    public IPage query(CollectQueryParam queryParam) {

        LambdaQueryWrapper<SpaceTrackCollectRecordPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(SpaceTrackCollectRecordPO::getId,SpaceTrackCollectRecordPO::getFileName,
                SpaceTrackCollectRecordPO::getStatus,SpaceTrackCollectRecordPO::getFileSize,SpaceTrackCollectRecordPO::getSatellite,
                SpaceTrackCollectRecordPO::getFileDesc,SpaceTrackCollectRecordPO::getFileDate,SpaceTrackCollectRecordPO::getDataType,SpaceTrackCollectRecordPO::getUploadTime);
        queryWrapper.like(StringUtils.hasLength(queryParam.getFileName()),SpaceTrackCollectRecordPO::getFileName,queryParam.getFileName());
        queryWrapper.eq(StringUtils.hasLength(queryParam.getSatellite()),SpaceTrackCollectRecordPO::getSatellite,queryParam.getSatellite());
        queryWrapper.eq(StringUtils.hasLength(queryParam.getStatus()),SpaceTrackCollectRecordPO::getStatus,queryParam.getStatus());
        queryWrapper.eq(StringUtils.hasLength(queryParam.getFileType()),SpaceTrackCollectRecordPO::getFileType,queryParam.getFileType());
        queryWrapper.eq(StringUtils.hasLength(queryParam.getDataType()),SpaceTrackCollectRecordPO::getDataType,queryParam.getDataType());
        //TLE 陨落数据 按上传时间排序
        if (CollectFileTypeConstants.TYPE_TLE.equals(queryParam.getFileType()) || CollectFileTypeConstants.TYPE_FALL.equals(queryParam.getFileType())) {
            queryWrapper.orderByDesc(SpaceTrackCollectRecordPO::getFileDate);
        }else {
            queryWrapper.orderByDesc(SpaceTrackCollectRecordPO::getFileDate);
        }
        queryWrapper.between(null != queryParam.getStartTime() && null!= queryParam.getEndTime(),SpaceTrackCollectRecordPO::getFileDate,queryParam.getStartTime(),queryParam.getEndTime());
        IPage page = recordService.page(queryParam.page(), queryWrapper);
        List<SpaceTrackDataCollectVO> objects = new ArrayList<>();
        for (Object obj : page.getRecords()) {
            SpaceTrackCollectRecordPO po = (SpaceTrackCollectRecordPO) obj;
            SpaceTrackDataCollectVO vo = TranferUtils.tranferTrackRecordPO(po);
            objects.add(vo);
        }
        page.setRecords(objects);
        return page;
    }

    @Override
    public List<String> uploadFile(MultipartFile[] files, String satellite, String fileType, String satelliteCode, String dataType) throws DataRepeatException {

        //单个文件,如果重复,直接抛异常
        if (files.length==1) {
            String filename = files[0].getOriginalFilename();
            int num = this.checkRepeat(filename);
            if (num>0) {
                //存在 不处理
                throw new DataRepeatException();
            }
        }

        List<SpaceTrackCollectRecordPO> list = new ArrayList<>(files.length);
        Date now = new Date();
        String midPath = "/track/"+ fileType;
        String fullPath = PathUtil.outputModuleDir(BizModule.COLLECT)+midPath;
        List<String> resList = new ArrayList<>();
        for (MultipartFile file : files) {

            String filename = file.getOriginalFilename();
            int num = this.checkRepeat(filename);
            if (num>0) {
                //存在 不处理
                resList.add(filename);
                continue;
            }

            SpaceTrackCollectRecordPO recordPO = new SpaceTrackCollectRecordPO();
            recordPO.setFileName(filename);
            recordPO.setFileType(fileType);
            recordPO.setFileSize(file.getSize());
            recordPO.setUploadTime(now);
            recordPO.setFilePath(midPath);
            recordPO.setStatus(CollectFileStatusEnum.FILE_WAIT.getCode());
            recordPO.setDataType(dataType);
            recordPO.setSatellite(satellite);
            try {
                File path = new File(fullPath, filename);
                FileUtil.mkParentDirs(path);
                file.transferTo(path);
                //通过filename 获取 信息
                //选择数据策略,并进行相应的的特殊化处理
                dataStrategyManager.switchStrategy(fileType,satellite,dataType).makeupPo(recordPO);

            }catch (Exception e) {
                log.error("",e);
                recordPO.setStatus(CollectFileStatusEnum.FILE_ERROR.getCode());
                recordPO.setFileDesc("保存异常，"+e.getMessage());
            }

            list.add(recordPO);
        }
        //保存到数据库
        recordService.saveBatch(list);
        for (SpaceTrackCollectRecordPO po : list) {
            analysisStrategyManager.analysisTrack(po);
        }
        return resList;
    }

    @Override
    public boolean delFile(Long id) {

        LambdaQueryWrapper<SpaceTrackCollectRecordPO> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(SpaceTrackCollectRecordPO::getFilePath,SpaceTrackCollectRecordPO::getFileName);
        wrapper.eq(SpaceTrackCollectRecordPO::getId,id);
        SpaceTrackCollectRecordPO po = recordService.getOne(wrapper);
        String fullPath = PathUtil.outputModuleDir(BizModule.COLLECT)+po.getFilePath()+"/"+ po.getFileName();
        new File(fullPath).delete();

        return recordService.removeById(id);
    }

    @Override
    public boolean delBatch(List<Long> ids) {
        LambdaQueryWrapper<SpaceTrackCollectRecordPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(SpaceTrackCollectRecordPO::getId,ids);
        queryWrapper.select(SpaceTrackCollectRecordPO::getFilePath,SpaceTrackCollectRecordPO::getFileName);
        List<SpaceTrackCollectRecordPO> pos = recordService.list(queryWrapper);
        if (null != pos) {
            for (SpaceTrackCollectRecordPO po : pos) {
                String fullPath = PathUtil.outputModuleDir(BizModule.COLLECT)+po.getFilePath()+"/"+ po.getFileName();
                new File(fullPath).delete();
            }
        }
        return recordService.removeByIds(ids);
    }

    @Override
    public String download(Long id) {
        SpaceTrackCollectRecordPO po = this.getById(id);
        File file = new File(PathUtil.outputModuleDir(BizModule.COLLECT)+po.getFilePath(), po.getFileName());
        return file.getAbsolutePath();
    }

    @Override
    public String downloadBatch(List<Long> ids) {
        List<SpaceTrackCollectRecordPO> list = recordService.listByIds(ids);
        String url = PathUtil.outputModuleDir(BizModule.COLLECT)+ "/"+DateUtil.format(new Date(),"yyyyMMddHHmmss")+".zip";
        if (CollectionUtil.isNotEmpty(list)) {
            File[] toZipArr = new File[list.size()];
            for (int i = 0; i < list.size(); i++) {
                toZipArr[i] = new File(PathUtil.outputModuleDir(BizModule.COLLECT)+list.get(i).getFilePath(),list.get(i).getFileName());
            }
            File zip = ZipUtil.zip(new File(url), false, toZipArr);
            url = zip.getAbsolutePath();
        }
        return url;
    }

    @Override
    public boolean analysis(Long id) {
        SpaceTrackCollectRecordPO po = recordService.getById(id);
        if (po.getStatus() == CollectFileStatusEnum.FILE_SUCC.getCode()) {
            throw new ServiceException("请勿重复解析");
        }else {
            LambdaUpdateWrapper<SpaceTrackCollectRecordPO> uw = new LambdaUpdateWrapper<>();
            uw.eq(SpaceTrackCollectRecordPO::getId,id);
            uw.set(SpaceTrackCollectRecordPO::getStatus,CollectFileStatusEnum.FILE_WAIT.getCode());
            recordService.update(uw);

            analysisStrategyManager.analysisTrack(po);
            return true;
        }

    }

    @Override
    public boolean analysisBatch(List<Long> ids) {
        //已解析的不再重复解析
        List<SpaceTrackCollectRecordPO> pos = listByIds(ids);
        ArrayList<Long> idLsit = new ArrayList<>();
        if (null != pos) {
            ArrayList<String> list = new ArrayList<>();
            for (SpaceTrackCollectRecordPO spaceTrackCollectRecordPO : pos) {
                if (spaceTrackCollectRecordPO.getStatus() != CollectFileStatusEnum.FILE_SUCC.getCode()) {
                    idLsit.add(spaceTrackCollectRecordPO.getId());
                }else {
                    list.add(spaceTrackCollectRecordPO.getFileName());
                }
            }
            if (CollectionUtil.isNotEmpty(idLsit)) {
                LambdaUpdateWrapper<SpaceTrackCollectRecordPO> uw = new LambdaUpdateWrapper<>();
                uw.in(SpaceTrackCollectRecordPO::getId,idLsit);
                uw.set(SpaceTrackCollectRecordPO::getStatus,CollectFileStatusEnum.FILE_WAIT.getCode());
                recordService.update(uw);
                for (SpaceTrackCollectRecordPO spaceTrackCollectRecordPO : pos) {
                    if (spaceTrackCollectRecordPO.getStatus() != CollectFileStatusEnum.FILE_SUCC.getCode()) {
                        analysisStrategyManager.analysisTrack(spaceTrackCollectRecordPO);
                    }

                }
            }
            if (CollectionUtil.isNotEmpty(list)) {
                throw new ServiceException("重复数据不再解析:"+ CollectionUtil.join(list,","));
            }

        }
        return true;
    }

    @Override
    public CollectEstimateVO lookRes(Long id) throws Exception {
        SpaceTrackCollectRecordPO po = recordService.getById(id);
        if (null != po && StringUtils.hasLength(po.getResFile())) {
            JSONObject jsonObject = JSON.parseObject(po.getResFile());
            CollectEstimateVO collectEstimateVO = new CollectEstimateVO();
            collectEstimateVO.setToal(jsonObject.getInteger("total"));
            collectEstimateVO.setError(jsonObject.getInteger("error"));
            return collectEstimateVO;
        }else {
            throw  new Exception("数据不存在或解析异常");
        }
    }


    @Override
    public String lookDetailRes(Long id) throws Exception {
        LambdaQueryWrapper<SpaceTrackCollectRecordPO> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(SpaceTrackCollectRecordPO::getResFile);
        wrapper.eq(SpaceTrackCollectRecordPO::getId,id);
        SpaceTrackCollectRecordPO po = recordService.getOne(wrapper);
        if (null != po && StringUtils.hasLength(po.getResFile())) {
            JSONObject jsonObject = JSON.parseObject(po.getResFile());
            String logFile = jsonObject.getString("logFile");
            String content = FileUtil.readString(logFile, Charset.forName("UTF-8"));
            return content;
        }else {
            throw  new Exception("数据不存在或解析异常");
        }
    }

    @Override
    public int checkRepeat(String filename) {
        return this.getBaseMapper().selectRepeat(filename);
    }

    @Override
    public List<CommonVO> findStatellite() {
        LambdaQueryWrapper<SpaceTargetMeasurePO> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(SpaceTargetMeasurePO::getName,SpaceTargetMeasurePO::getCode);
        List<SpaceTargetMeasurePO> list = measureService.list(wrapper);
        List<CommonVO> vos = list.stream().map(a -> {
            return new CommonVO(a.getCode(), a.getName());
        }).collect(Collectors.toList());
        return vos;
    }

}
